// std_out.hxx


#ifndef _BLOGS_STD_OUT
#define _BLOGS_STD_OUT


#include <iomanip>
#include <iostream>
#include <string>

#include "array.hxx"


namespace blogs
{


using std::cout;
using std::endl;
using std::string;


class Std_Out
{

  public:

    /*
     * Print arguments in the specified format.
     *
     * NOTE:
     *  It requires a C-string when printing a string object.
     *
     * NOTE:
     *  Using 'Variadic Template' feature from C++11.
     *
     */
    //template <class... Types>
    //static
    //void
    //printf(char const* fmt, Types const&... args)
    //{
    //    std::fprintf(stdout, fmt, args...);
    //    // or
    //    // std::printf(fmt, args...);
    //}


    /*
     * Print arguments in the specified format.
     *
     * NOTE:
     *   It requires a C-string when printing a string object.
     *
     * NOTE:
     *  Using 'Variadic Fuction' feature from C++11.
     *
     */
    static
    void
    printf(char const*, ...);


    /*
     * Print a newline.
     *
     */
    static
    void
    println();


    /*
     * Print a value.
     *
     */
    template <class _T>
    static
    void
    print(_T const& v)
    {
        cout << v;
    }


    /*
     * Print a boolean value.
     *
    template <>
    //
    // NOTE:
    //  compile warning : explicit specialization cannot have a storage class
    //  so 'static' is commented.
    //static
    //
    void
    print<bool>(bool const& v)
    {
        cout << (v ? "true" : "false");
    }
     */


    /*
     * Print a value ending with a newline.
     *
     */
    template <class _T>
    static
    void
    println(_T const& v)
    {
        cout << v << endl;
    }


    /*
     * Print a boolean value ending with a newline.
     *
    template <>
    //
    // NOTE:
    //  compile warning : explicit specialization cannot have a storage class
    //  so 'static' is commented.
    //static
    void
    println<bool>(bool const& v)
    {
        cout << (v ? "true" : "false") << endl;
    }
     */


    /*
     * Print the array according to the arguments,
     *  m   -   array object
     *  p   -   precision
     *  w   -   cell width
     *
     */
    template <class _T>
    static
    void
    println(Array<_T> const& a, int p = 6, int w = 0)
    {
        cout << std::setprecision(p);
        for (int i = 0; i < a.size(); ++i) {
            cout << " " << std::setw(w);
            print<_T>(a[i]);     // Using template explicit specialization to print a boolean value.
        }
        cout << endl;
    }

};


} // end of namespace blogs


#endif

